package com.sti.framework.models.User.controller;

import com.sti.framework.core.annotation.authorization.Authorization;
import com.sti.framework.core.data.IDEntity;
import com.sti.framework.core.encryption.aes.AESUtil;
import com.sti.framework.core.redis.RedisUtil;
import com.sti.framework.core.security.jwt.JwtException;
import com.sti.framework.core.security.jwt.JwtUtil;
import com.sti.framework.core.web.Page;
import com.sti.framework.core.web.ResponseBodyEntity;
import com.sti.framework.core.web.SimplePage;
import com.sti.framework.models.User.data.Logs;
import com.sti.framework.models.User.data.Role;
import com.sti.framework.models.User.data.User;
import com.sti.framework.models.User.data.UserSearchWhere;
import com.sti.framework.models.User.service.LogsService;
import com.sti.framework.models.User.service.PhoneCodeService;
import com.sti.framework.models.User.service.RoleService;
import com.sti.framework.models.User.service.UserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/Api/User")
@Api(tags = "用户管理", value = "用户管理")
public class UserController {

    @Inject
    private UserService userService;
    @Inject
    private LogsService logsService;
    @Resource
    private RedisUtil redisUtil;
    @Inject
    private RoleService roleService;

    @Value("${spring.SingleClientVerification}")
    private boolean singleClientVerification;

    @ApiOperation(value = "用户列表")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @Authorization(tag = "/List", describes = "用户列表")
    @GetMapping("/List")
    public ResponseBodyEntity<SimplePage<User>> List(Page page, UserSearchWhere searchWhere) {
        searchWhere.setPhone(AESUtil.AESEncrypt(searchWhere.getPhone(), AESUtil.key, "CBC"));
        return ResponseBodyEntity.success(userService.getAll(page, searchWhere));
    }

    @ApiOperation(value = "用户详情")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @Authorization(tag = "/List", describes = "用户列表")
    @GetMapping("/Info")
    public ResponseBodyEntity<User> Info(HttpServletRequest request, @Valid IDEntity id) {
        return ResponseBodyEntity.success(userService.get(id.getId()));
    }

    @ApiOperation(value = "使用token获取用户详情")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @GetMapping("/InfoByToken")
    public ResponseBodyEntity<User> InfoByToken(HttpServletRequest request, @Valid @NotNull String token) {

        Claims claims = JwtUtil.checkJWT(token);
        Long user_id = claims.get("user_id", Long.class);

        // 检查redis
        if (singleClientVerification) {
            String redistoken = (String) redisUtil.get("Session_" + user_id);
            if (redistoken == null || !redistoken.equals(token)) {
                throw new JwtException(ResponseBodyEntity.ResponseStatus.TOKENEXPIREDCLIENT);
            }
        }
        return ResponseBodyEntity.success(userService.get(user_id));
    }

    @ApiOperation(value = "创建用户")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @Authorization(tag = "/Create", describes = "创建用户")
    @PostMapping(value = "/Create")
    public ResponseBodyEntity Create(@RequestBody @Valid User user) {
        //获取角色数据
        Role role = roleService.get(user.getRole_id());
        if (role != null) {
            user.setRole(role.getName());
        }
        userService.create(user);
        return ResponseBodyEntity.success();
    }

    @ApiOperation(value = "修改用户")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @Authorization(tag = "/Modify", describes = "修改用户")
    @PostMapping(value = "/Modify")
    public ResponseBodyEntity Modify(@RequestBody @Valid User user, IDEntity id) {
        //获取角色数据
        Role role = roleService.get(user.getRole_id());
        if (role != null) {
            user.setRole(role.getName());
        }
        userService.updateById(user);
        return ResponseBodyEntity.success();
    }

    @ApiOperation(value = "使用token修改用户")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @PostMapping(value = "/ModifyByToken")
    public ResponseBodyEntity ModifyByToken(@RequestBody @Valid User user, HttpServletRequest request) {
        Long userid = Long.parseLong(request.getAttribute("user_id").toString());
        user.setId(userid);
        userService.update(user);
        return ResponseBodyEntity.success();
    }

    @ApiOperation(value = "删除用户")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @Authorization(tag = "/Remove", describes = "删除用户")
    @PostMapping(value = "/Remove")
    public ResponseBodyEntity Remove(@RequestBody @Valid IDEntity id) {
        userService.delete(Long.valueOf(id.getId()));
        return ResponseBodyEntity.success();
    }

    @ApiOperation(value = "登陆")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "body", dataTypeClass = String.class, example = "aarongao"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "body", dataTypeClass = String.class, example = "123456"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "body", dataTypeClass = String.class, example = "1234"),
            @ApiImplicitParam(name = "key", value = "验证码密钥", required = true, paramType = "body", dataTypeClass = String.class, example = ""),
    })
    @PostMapping(value = "/Login")
    public ResponseBodyEntity<User> Login(@RequestBody Map<String, String> user) {

        String username = user.get("username");
        String password = user.get("password");
        String code = user.get("code");
        String key = user.get("key");

        Claims claims = JwtUtil.checkJWT(key);
        String decode = claims.get("code", String.class);
        if (!code.equals(decode)) {
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "验证码不正确");
        }
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "用户名或密码不能为空");
        }

        String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
        User user2 = userService.get(username, md5Password);
        if (user2 == null) {
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "用户名或密码不正确");
        }
//         if (user2.getStatus() == "禁用") {
//             return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "用户已禁用");
//         }

        String token = geneJsonWebToken(user2);
        user2.setToken(token);

        // 写入redis
        redisUtil.set("Session_" + user2.getId(), token, JwtUtil.EXPIRE);

        // 记录登陆日志
        Logs log = new Logs();
        log.setUsername(user2.getUsername());
        log.setUserid(user2.getId());
        log.setTable_name("用户管理");
        log.setTag("/Api/User/Login");
        log.setAction("登陆");
        logsService.create(log);

        return ResponseBodyEntity.success(user2);
    }


    @ApiOperation(value = "刷新token")
    @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true)
    @PostMapping(value = "/RefreshToken")
    public ResponseBodyEntity RefreshToken(HttpServletRequest request) {

        String token = request.getHeader("token");
        Claims claims = JwtUtil.checkJWT(token);
        Long user_id = claims.get("user_id", Long.class);

        // 检查redis
        String redistoken = (String) redisUtil.get("Session_" + user_id);
        if (!redistoken.equals(token)) {
            throw new JwtException(ResponseBodyEntity.ResponseStatus.TOKENEXPIREDCLIENT);
        }

        User user = userService.get(user_id);
        token = geneJsonWebToken(user);

        // 写入redis
        redisUtil.set("Session_" + user.getId(), token, JwtUtil.EXPIRE);
        user.setToken(token);

        // 记录登陆日志
        Logs log = new Logs();
        log.setUsername(user.getUsername());
        log.setUserid(user.getId());
        log.setTable_name("用户管理");
        log.setTag("/Api/User/RefreshToken");
        log.setAction("刷新Token");
        logsService.create(log);

        Map<String, String> res = new HashMap<String, String>();
        res.put("token", token);
        return ResponseBodyEntity.success(res);
    }

    @ApiOperation(value = "修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "登陆后获取的签名", paramType = "header", dataTypeClass = String.class, required = true),
            @ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "body", dataTypeClass = String.class, example = "aarongao"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "body", dataTypeClass = String.class, example = "123456"),
            @ApiImplicitParam(name = "new_password", value = "验证码", required = true, paramType = "body", dataTypeClass = String.class, example = "1234"),
    })

    @PostMapping(value = "/ModifyPassword")
    public ResponseBodyEntity ModifyPassword(@RequestBody Map<String, String> user) {

        String username = user.get("username");
        String password = user.get("password");
        String new_password = user.get("new_password");
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(new_password)) {
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "用户名或密码(包括新密码)不能为空");
        }
        User user2 = userService.get(username, password);
        if (user2 == null) {
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "用户名或密码不正确");
        }
        user2.setPassword(new_password);
        userService.update(user2);
        return ResponseBodyEntity.success();
    }

    @ApiOperation(value = "重置密码")
    @Authorization(tag = "/Modify", describes = "重置密码")
    @GetMapping(value = "/RestUserPass")
    public ResponseBodyEntity restPass(@RequestParam Long id) {
        User user = userService.get(id);
        user.setPassword("123456");
        user.setIsEncipherFlag("1");
        userService.update(user);
        return ResponseBodyEntity.success();
    }

    // 生成 JWT (User)
    public static String geneJsonWebToken(User user) {

        if (user == null ||
                user.getId() == null ||
                (user.getUsername() == null && user.getPhone() == null)
        ) {

            return null;
        }
        return Jwts.builder()
                .setSubject(JwtUtil.SUBJECT)
                .claim("user_id", user.getId())
                .claim("username", user.getUsername())
                .claim("role_id", user.getRole_id())
                .claim("phone", user.getPhone())
                .claim("realNamer", user.getRealNamer())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + JwtUtil.EXPIRE * 1000))
                .signWith(SignatureAlgorithm.HS256, JwtUtil.SECRETKEY).compact();
    }
}
